///////////////////
// Asynch
///////////////////

var xmlHttpRequester=new XMLHttpRequest();

function sendRequest(url,callback,postData) {
	var req = xmlHttpRequester;
	if (!req) return;
	var method = (postData) ? "POST" : "GET";
	req.open(method,url,true);
	req.setRequestHeader('User-Agent','XMLHTTP/1.0');
	if (postData)
		req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
	req.onreadystatechange = function () {
		if (req.readyState != 4) return;
		if (req.status != 200 && req.status != 304) {
//			alert('HTTP error ' + req.status);
			return;
		}
		callback(req);
	}
	if (req.readyState == 4) return;
	req.send(postData);
}

///////////////////
// Votes
///////////////////

function sendYesVote(elem) {
  var tr=elem.parentNode.parentNode;
  var yes=parseInt(tr.getAttribute("yes"));
  var geoId=parseInt(tr.getAttribute("geoId"));
  tr.setAttribute("yes",yes+1);
  elem.innerHTML=yes+1;
  sendRequest('vote.jsp?vote=yes&id='+geoId, handleRequest);
}

function sendNoVote(elem) {
  var tr=elem.parentNode.parentNode;
  var no=parseInt(tr.getAttribute("no"));
  var geoId=parseInt(tr.getAttribute("geoId"));
  tr.setAttribute("no",no+1);
  elem.innerHTML=no+1;
  sendRequest('vote.jsp?vote=no&id='+geoId, handleRequest);
}

function handleRequest(req) { 
//  var results = req.responseText.split(",");
}

///////////////////
// Coordinates
///////////////////

function getCoordinates() {

  var useGeoLocation=localStorage.getItem("useGeoLocation");
  if (useGeoLocation==null || useGeoLocation=="true") {
    updateGeoStatus(waitingForCoordinatesMessage);
    var geolocation = navigator.geolocation;
    if (geolocation) {
      var parameters={enableHighAccuracy:true, maximumAge:20000, timeout:20000};
      geolocation.watchPosition(setPosition,displayError,parameters);
    } else {
      updateGeoStatus(locationNotAvailableMessage);
    }
  } else {
    var display=accuracyLabel + ": " + localStorage.getItem("accuracy") + "m";
    updateGeoStatus(display);
    updateNotesDispay();

    // Update buttons
    document.getElementById("addButtonDisabled").style.display='none';
    document.getElementById('addButtonEnabled').style.display='inline';
  }
}

// Set global variables holding the position
function setPosition(position){
  var display="N/A";
  if (position){
    // Set global variables
    localStorage.setItem("latitude", position.coords.latitude);
    localStorage.setItem("longitude", position.coords.longitude);
    localStorage.setItem("accuracy", position.coords.accuracy);

    // Display accuracy
    display=accuracyLabel + ": " + position.coords.accuracy + "m";

    // Update buttons
    document.getElementById("addButtonDisabled").style.display='none';
    document.getElementById('addButtonEnabled').style.display='inline';

    updateNotesDispay();
  }
  updateGeoStatus(display);
}

function setCoorindatesFormFields(){
    document.getElementById("latitude").value=localStorage.getItem("latitude");
    document.getElementById("longitude").value=localStorage.getItem("longitude");
    document.getElementById("accuracy").value=localStorage.getItem("accuracy");
}

if (typeof(Number.prototype.toRad) === "undefined") {
  Number.prototype.toRad = function() {
    return this * Math.PI / 180;
  }
}

// Converts radians to numeric (signed) degrees
if (typeof(Number.prototype.toDeg) === "undefined") {
  Number.prototype.toDeg = function() {
    return this * 180 / Math.PI;
  }
}

function calculateDistance(lat1, lon1, lat2, lon2) {
  var R = 6371; // km
  var dLat = (lat2-lat1).toRad();
  var dLon = (lon2-lon1).toRad();
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
          Math.sin(dLon/2) * Math.sin(dLon/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c;
  return d;
}

function calculateBearing(lat1, lon1, lat2, lon2) {
  var dLon=(lon2-lon1).toRad();
  var lat1r=lat1.toRad();
  var lat2r=lat2.toRad();
  var y = Math.sin(dLon) * Math.cos(lat2r);
  var x = Math.cos(lat1r)*Math.sin(lat2r) -
          Math.sin(lat1r)*Math.cos(lat2r)*Math.cos(dLon);
  var bearing = Math.atan2(y, x).toDeg();
  return (bearing+360)%360;
}

///////////////////
// Sorting
///////////////////

function reorderGeoNotes(sortFunction) {
  var geoNotes=document.getElementById("geoNotes");
  var notes=geoNotes.getElementsByTagName("tr");
  var notesTemp=new Array();
  for (var i=1; i<notes.length; i++) {
    notesTemp.push(notes[i]);
  }
  notesTemp.sort(sortFunction);
  for (var i=0; i<notesTemp.length; i++) {
    geoNotes.appendChild(notesTemp[i]);
  }
}

function sortByDistanceAscending(note1,note2) {
  var distance1=parseFloat(note1.getAttribute("distance"));
  var distance2=parseFloat(note2.getAttribute("distance"));  
  if (distance2>distance1) {
      return -1;
  } else if (distance1>distance2) {
      return 1;
  } else {
      return 0;
  }
}

function sortByTimeDescending(note1,note2) {
  var time1=parseFloat(note1.getAttribute("time"));
  var time2=parseFloat(note2.getAttribute("time"));  
  if (time1>time2) {
      return -1;
  } else if (time2>time1) {
      return 1;
  } else {
      return 0;
  }
}

function sortByVoteYesDescending(note1,note2) {
  var vote1=parseInt(note1.getAttribute("yes"));
  var vote2=parseInt(note2.getAttribute("yes"));  
  if (vote1>vote2) {
      return -1;
  } else if (vote2>vote1) {
      return 1;
  } else {
      return 0;
  }
}

function sortByVoteNoDescending(note1,note2) {
  var vote1=parseInt(note1.getAttribute("no"));
  var vote2=parseInt(note2.getAttribute("no"));  
  if (vote1>vote2) {
      return -1;
  } else if (vote2>vote1) {
      return 1;
  } else {
      return 0;
  }
}

function reorderGeoNotesByTimeDescending() {
  localStorage.setItem("sortBy","time");
  reorderGeoNotes(sortByTimeDescending);
}

function reorderGeoNotesByDistanceAscending() {
  localStorage.setItem("sortBy","distance");
  reorderGeoNotes(sortByDistanceAscending);
}

function reorderGeoNotesByVoteYesDescending() {
  localStorage.setItem("sortBy","voteYes");
  reorderGeoNotes(sortByVoteYesDescending);
}

function reorderGeoNotesByVoteNoDescending() {
  localStorage.setItem("sortBy","voteNo");
  reorderGeoNotes(sortByVoteNoDescending);
}

///////////////////
// Display
///////////////////

function updateNotesDispay() {

  // Current location
  var latitude=parseFloat(localStorage.getItem("latitude"));
  var longitude=parseFloat(localStorage.getItem("longitude"));
  var currentSeconds=new Date().getTime()/1000;
  
  // For each note
  var geoNotes=document.getElementById("geoNotes");
  var notes=geoNotes.getElementsByTagName("tr");
  for (var i=1; i<notes.length; i++) {
    var note=notes[i];
    var noteLat=parseFloat(note.getAttribute("lat"));
    var noteLon=parseFloat(note.getAttribute("lon"));
    var display="";

    // Distance
    var distance=calculateDistance(latitude, longitude, noteLat, noteLon);

    // Save for ordering
    note.setAttribute("distance",distance);

    // Add distance to display
    if (distance<1){
      display=Math.round(distance*1000)+"m";
    } else {
      display=Math.round(distance*10)/10 +"km";
    }

    // Bearing
    var bearingDegrees=calculateBearing(latitude, longitude, noteLat, noteLon);
    display+=" " + getCardinalDirection(bearingDegrees);

    // Update direction display
    note.getElementsByTagName("td")[0].innerHTML=display;
   
    // Update time display
    note.getElementsByTagName("td")[1].innerHTML=getElapsedTime(parseInt(note.getAttribute("time")),currentSeconds);
  }

  // Sort
  var sortBy=localStorage.getItem("sortBy");
  if (sortBy==null || sortBy=="distance") {
    reorderGeoNotesByDistanceAscending();
  } else if (sortBy=="time") {
    reorderGeoNotesByTimeDescending();
  } else if (sortBy=="voteYes") {
    reorderGeoNotesByVoteYesDescending();
  } else if (sortBy=="voteNo") {
    reorderGeoNotesByVoteNoDescending();
  }
}

function getCardinalDirection(degrees) {
  var value;
  if (degrees>=22.5 && degrees<=67.5){
    value="NE";
  } else if (degrees>67.5 && degrees<112.5) {
    value="E";
  } else if (degrees>=112.5 && degrees<=157.5) {
    value="SE";
  } else if (degrees>157.5 && degrees<202.5) {
    value="S";
  } else if (degrees>=202.5 && degrees<=247.5) {
    value="SW";
  } else if (degrees>247.5 && degrees<292.5) {
    value="W";
  } else if (degrees>=292.5 && degrees<=337.5) {
    value="NW";
  } else {
    value="N";
  }
  return value;
}

function getElapsedTime(oldSeconds,newSeconds){
  var display="";
  var seconds=newSeconds-oldSeconds;
  if (seconds<60){
    display=Math.round(seconds)+" sec";
  } else {
    var minutes=seconds/60;
    if (minutes<60) {
      display=Math.round(minutes)+" min";
    } else {
      var hours=minutes/60;
      if (hours<24) {
        display=Math.round(hours)+" hr";
      } else {
        var days=hours/24;
        display=Math.round(days)+" day";
      }
    }
  }
  return display;
}

function displayError(error){
  updateGeoStatus(locationNotFoundMessage + ": (" + error.code + ") " + error.message);
}

function updateGeoStatus(text) {
  document.getElementById("geoStatus").innerHTML=text;
}